//
//  main.m
//  C07_指针
//
//  Created by dllo on 15/11/25.
//  Copyright © 2015年 dllo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Fuction.h"

int main(int argc, const char * argv[]) {
   
#pragma mark - 知识点1 C 语言指针的概念
    /** 指针就是内存地址  通过指针同样可以访问内存中的内容*/
    
    
#pragma mark - 知识点2 指针变量的定义和使用
    
    /** 定义一个指针变量 */
    /** 指针变量P,表示将访问一个地址之上4个字节的内存空间.
     * NULL 的含义是, 将P指向了0*0地址(空指针)
     */
//    int *p = NULL;
//    
//    long *p2 =NULL;
    
    /** 指针变量 p 本身也需在再内存中保存, 指针变量占用内存字节数取决于系统. 64位系统占8个字节,32位占4个字节 */
    
    
#pragma mark - 知识点3 指针的算术运算( '&' 运算符和 '*' 运算符)
    
    /** & 的使用. 作用: 取出内存地址(取址符) */
    int a = 100;
    
    int *p = NULL;/* 定义一个指针,指向空*/
    
    p = &a; /* 将指针p指向 变量a的内存地址*/
    
    printf("p:%p", p);/*输出p的地址*/   /* '%p' 是输出地址*/
    printf("a:%p",&a);/*输出a的地址*/
    printf("over\n");
//
//    /*  '*' 符号: 取出指针指向的内存地址中的内容(取值符) */
//    *p = 201;/*相当于a=201*/
//    printf("%d\n",*p);
//    
    
    
//    int b = 200;
//    short *ps = &b;
//    printf("%hd\n", *ps);
    
    int c = 300;
    
    int *p = NULL;
    p = &c;
    p++;
    printf("p:%p\n", p);
    printf("p++:%p\n", ++p);
    
# pragma mark 练习
    /* (1)  交换两个int型的变量的值用指针体现*/
#if 0
    int a = 100;
    int b = 200;
    int *p = NULL;
    int *p1 = NULL;
    p = &a;
    p1 = &b;
    int temp = *p;
    *p = *p1;
    *p1 = temp;
   
    printf("a = %d, b = %d\n", a ,b);
#endif
    /*用函数实现练习1  即交换两个int类型变量值*/
#if 0
    int a = 100;
    int b = 200;
    /*调用函数*/
    exchangeTwoNumber(&a, &b);
    printf("a: %d, b:%d\n", a, b);
    
#endif
  

    
    
#pragma mark - 知识点4 指针和数组的关系
    /** */
#if 0
    int array[5] = {1, 2, 3, 4, 5};
    int *p = NULL;/* p+1,访问后4个字节的内容*/
    int (*p2)[5]=NULL;/* p2+1, 访问后20个字节内容,  相当于一个数组的长度*/
    p = array;
    p2= &array;
    printf("p:%p\n",p);
    printf("arr: %p\n", array);/* 数组名*/
    printf("arr: %p\n", &array);/* 数组的首地址*/
    printf("arr: %p\n", &array[0]);/* 第一个元素的首地址*/
    /* 结论   数组名即是数组的首地址,也是第一个元素的首地址 !!! */
#endif
    
#if 0
    /* 通过指针,遍历数组 */
    int array[5] = {1, 2, 3, 4, 5};
    int *p1 = NULL;
    
    p1 = array;
    
    for (int i = 0; i < 5; i++) {
        printf("%d\n", *(p1 + i));
    }
    for (int i = 0; i < 5; i++) {
        printf("%d\n", *(p1++));
    }
    
    for (int i = 0; i < 5; i++) {
        printf("%d\n", *p1++);
    }
#endif
    /* 拓展内容*/
//    int *point[5];/* 指针数组 */
//    int (*point1)[5];/* 数组指针 */
//
    /* 用指针实现冒泡排序 */
#if 0
    int array[5] = {1, 7, 3, 4, 5};
    int *p = NULL;
    p = array;
    int temp = 0;
    for (int i = 0; i < 5 - 1; i++) {
        for (int j = 0; j < 5 - 1 -i; j++) {
            if (*(p + j) > *(p + j + 1)) {
                temp = *(p + j);
                *(p + j) = *(p + j + 1);
                *(p + j + 1) = temp;
            }
        }
    }
    for (int i = 0; i < 5; i++) {
        printf("%d ", *(p + i));
    }
    
#endif
    
#if 0
    /* 指针作为函数的参数*/
    /* 使用函数实现冒泡排序 */
    int array[5] = {2,3,1,3,6};
    int *p = array;
    sortArr(p, 5);
    sortArr(array, 5);/* array数组名就是首地址 */
    
#endif
    
#pragma mark - 知识点5 指针和字符串的关系
    
//    printf(<#const char *restrict, ...#>);
//    strcmp(<#const char *#>, <#const char *#>);
//    strcpy(<#char *#>, <#const char *#>);
    /* const 修饰词的作用 */
//    int a  = 100;
//    a = 101;
//    const int b = 200;
//    b = 201; /* 经过const修饰的变量不能修改 起到保护作用 */
  
#if 0
    /* 使用指针输出字符串 (while)*/
    char string[] = "iphone";
    
    char *p = string;/* 指针指向字符串首地址 */
    int i = 0;
    while (*(p + i) != '\0') {
        printf("%c\n", *(p + i));
               i++;
    }
    /* 方法2 */
    while (*p) {
        printf("%c\n", *(p++));
    }
    
#endif
    /* 使用指针输出字符串 (for)*/
#if 0
    char string[] = "iphone";
    
    char *p = string;/* 指针指向字符串首地址 */
   
    for (int i = 0; i < strlen(string); i++) {
        printf("%c\n", *(p + i));
    }
#endif
    
    /* 通过指针计算字符串的长度 */
    char string[] = "iphone";
    
    char *p0 = string;/* 指针指向字符串首地址 */
    int count = 0;
    while (*p0) {
        count++;
        p0++;
         }
    printf("count = %d \n", count);

    
    return 0;
}







